<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\mvc;

interface ICommand
{
  /**
   * Creates new Command from Router - factory
   *
   * @param \crcl\base\mvc\router\IConcrete $oRouter
   *
   * @return \crcl\base\mvc\ICommand
   */
  public static function fromRouter(\crcl\base\mvc\router\IConcrete $oRouter);

  /**
   * Returns \TRUE if group is set, \FALSE otherwise
   *
   * @return bool
   */
  public function hasGroup();

  /**
   * Group setter
   *
   * @chainable
   * @param string $sGroup
   */
  public function setGroup($sGroup);

  /**
   * Group getter
   *
   * @return string
   */
  public function getGroup();

  /**
   * Controller setter
   *
   * @param string $sController
   */
  public function setController($sController);

  /**
   * Controller getter
   *
   * @chainable
   * @return string
   */
  public function getController();

  /**
   * Action setter
   *
   * @chainable
   * @param string $sAction
   */
  public function setAction($sAction);

  /**
   * Action getter
   */
  public function getAction();

  /**
   * Returns \TRUE if version is set, \FALSE otherwise
   *
   * @return bool
   */
  public function hasVersion();

  /**
   * Version setter
   *
   * @chainable
   * @param string $sVersion
   */
  public function setVersion($sVersion);

  /**
   * Version getter
   *
   * @return string
   */
  public function getVersion();

  /**
   * Method setter
   *
   * @chainable
   * @param string $sMethod
   */
  public function setMethod($sMethod);

  /**
   * Method getter
   *
   * @return string
   */
  public function getMethod();

  /**
   * View setter
   *
   * @chainable
   * @param string $sView
   */
  public function setView($sView);

  /**
   * View getter
   *
   * @return string
   */
  public function getView();

  /**
   * Values setter
   *
   * @chainable
   * @param \crcl\base\mvc\IValues $oValues
   */
  public function setValues($oValues);

  /**
   * Values getter
   *
   * @return \crcl\base\mvc\IValues
   */
  public function getValues();

  /**
   * Status setter
   *
   * @chainable
   * @param int $iStatus
   */
  public function setStatus($iStatus);

  /**
   * Status getter
   *
   * @return int
   */
  public function getStatus();

  /**
   * Xhtml setter
   *
   * @chainable
   * @param int $bXhtml
   */
  public function setXhtml($bXhtml);

  /**
   * Xhtml getter
   *
   * @return boolean
   */
  public function hasXhtml();

  /**
   * Headers setter
   *
   * @chainable
   * @param array $aHeaders
   */
  public function setHeaders($aHeaders);

  /**
   * Header setter
   *
   * @chainable
   * @param string $sName
   * @param mixed $value
   */
  public function addHeader($sName, $value);

  /**
   * Headers getter
   *
   * @return array
   */
  public function getHeaders();

  /*
  public function setValue($sKey, $sValue);
  public function getValue($sKey);

  public function setType($sType);
  public function getType();

  public function setRedirect($bRedirect = \TRUE);
  public function isRedirect();

  public function setDone($bDone = \TRUE);
  public function isDone();

  public function setLast($bLast = \TRUE);
  public function isLast();

  public function setTemplate($sTemplate);
  public function getTemplate();

  public function setTemplateDefault($sTemplate);
  public function getTemplateDefault(); */
}

class Command implements ICommand
{
  /*const TYPE_HTML = 'html';
  const TYPE_JSON = 'json';
  const TYPE_JS   = 'js';

  //request type which is not handled by mvc (like non existing files)
  const TYPE_404  = 'nothandled';
*/

  public static function fromRouter(\crcl\base\mvc\router\IConcrete $oRouter)
  {
    $oCommand = new \crcl\base\mvc\Command();
    $oCommand->setGroup($oRouter->getGroup());
    $oCommand->setController($oRouter->getController());
    $oCommand->setAction($oRouter->getAction());
    $oCommand->setMethod($oRouter->getMethod());
    $oCommand->setView($oRouter->getView());
    $oCommand->setXhtml($oRouter->hasXhtml());

    return $oCommand;
  }

  public function hasGroup()
  {
    if (!\is_null($this->sGroup))
    {
      return \TRUE;
    }
    return \FALSE;
  }

  public function setGroup($sGroup)
  {
    $this->sGroup = $sGroup;
    $this->formatGroup();

    return $this;
  }

  public function getGroup()
  {
    return $this->sGroup;
  }

  public function setController($sController)
  {
    $this->sController = $sController;
    $this->formatController();

    return $this;
  }

  public function getController()
  {
    return $this->sController;
  }

  public function getControllerWithNamespace()
  {
    $sResult = \crcl\base\application\Path::getNamespaceSubproject();
    $sResult .= 'controller' . '\\';
    if ($this->hasGroup())
    {
      $sResult .= $this->getGroup() . '\\';
    }
    $sResult .= $this->getController();

    return $sResult;
  }

  public function setAction($sAction)
  {
    $this->sAction = $sAction;
    $this->formatAction();

    return $this;
  }

  public function getAction()
  {
    return $this->sAction;
  }

  public function getActionWithMethod()
  {
    $sResult = $this->sMethod;
    $sResult .= \ucfirst($this->sAction);
    return $sResult;
  }

  public function hasVersion()
  {
    if (!\is_null($this->sVersion))
    {
      return \TRUE;
    }
    return \FALSE;
  }

  public function setVersion($sVersion)
  {
    $this->sVersion = $sVersion;

    return $this;
  }

  public function getVersion()
  {
    return $this->sVersion;
  }

  public function setMethod($sMethod)
  {
    $this->sMethod = $sMethod;
    $this->formatMethod();

    return $this;
  }

  public function getMethod()
  {
    return $this->sMethod;
  }

  public function setView($sView)
  {
    $this->sView = $sView;

    return $this;
  }

  public function getView()
  {
    return $this->sView;
  }

  public function setValues($oValues)
  {
    $this->oValues = $oValues;

    return $this;
  }

  public function getValues()
  {
    if (\is_null($this->oValues))
    {
      $this->oValues = new \crcl\base\mvc\Values();
    }
    return $this->oValues;
  }

  public function setStatus($iStatus)
  {
    $this->iStatus = $iStatus;

    return $this;
  }

  public function getStatus()
  {
    return $this->iStatus;
  }

  public function setXhtml($bXhtml)
  {
    $this->bXhtml = $bXhtml;

    return $this;
  }

  public function hasXhtml()
  {
    return $this->bXhtml;
  }

  public function setHeaders($aHeaders)
  {
    $this->aHeaders = $aHeaders;

    return $this;
  }

  public function addHeader($sName, $value)
  {
    $this->aHeaders[$sName] = $value;
  }

  public function getHeaders()
  {
    return $this->aHeaders;
  }

/*

  public function setValue($sKey, $sValue)
  {
    $this->_aValues[$sKey] = $sValue;
  }

  public function getValue($sKey)
  {
    if (isset($this->_aValues[$sKey]))
    {
      return $this->_aValues[$sKey];
    }
    throw new Exception('Value does not exist',
      Exception::ERROR_VALUEDOESNOTEXIST,
      array('key' => $sKey));
  }

  public function setType($sType)
  {
    $this->_sType = $sType;
  }

  public function getType()
  {
    return $this->_sType;
  }

  public function setRedirect($bRedirect = \TRUE)
  {
    $this->_bRedirect = $bRedirect;
  }

  public function isRedirect()
  {
    return $this->_bRedirect;
  }

  public function setDone($bDone = \TRUE)
  {
    $this->_bDone = $bDone;
  }

  public function isDone()
  {
    return $this->_bDone;
  }

  public function setLast($bLast = \TRUE)
  {
    $this->_bLast = $bLast;
  }

  public function isLast()
  {
    return $this->_bLast;
  }

  public function setTemplate($sTemplate)
  {
    $this->_sTemplate = $sTemplate;
  }

  public function getTemplate()
  {
    return $this->_sTemplate;
  }

  public function setTemplateDefault($sTemplate)
  {
    $this->_sTemplateDefault = $sTemplate;
  }

  public function getTemplateDefault()
  {
    return $this->_sTemplateDefault;
  }
*/
  /* PRIVATE **************************************************************************************/

  private $sGroup      = \NULL;
  private $sController = \NULL;
  private $sAction     = \NULL;
  private $sMethod     = \NULL;
  private $sVersion    = \NULL;
  private $sView       = View::TYPE_DEFAULT;
  private $oValues     = \NULL;
  private $iStatus     = \NULL;
  private $bXhtml      = \FALSE;
  private $aHeaders    = \NULL;

  //private $_sType            = self::TYPE_HTML;

  //private $_bRedirect        = FALSE;
  //private $_bDone            = \FALSE;
  //private $_bLast            = \FALSE;
  //private $_sTemplate        = \FALSE;
  //private $_sTemplateDefault = \FALSE;

  private function formatController()
  {
    $this->sController = \strtolower($this->sController);
    $this->sController = \ucFirst($this->sController);
  }

  private function formatMethod()
  {
    $this->sMethod = \strtolower($this->sMethod);
  }

  private function formatAction()
  {
    $this->sAction = \strtolower($this->sAction);
  }

  private function formatGroup()
  {
    if ($this->sGroup == '')
    {
      $this->sGroup = \NULL;
    }
    else
    {
      $this->sGroup = \strtolower($this->sGroup);
    }
  }
}